Skip to content

feat(FilterSummaryBar): active-filter summary bar for data grids - #400

Merged
garrity-miepub merged 9 commits into
mainfrom
feat/filter-summary-bar
Sep 4, 2026
Merged

feat(FilterSummaryBar): active-filter summary bar for data grids#400
garrity-miepub merged 9 commits into
mainfrom
feat/filter-summary-bar

Conversation

@ebellamy-bh

Copy link
Copy Markdown
Contributor

Ports the bar that anchors every filtered waggleline grid into the design system: "1,204 of 8,911 records — 3 filters active · Clear all".

What it does

  • Summarizes filteredCount / totalCount / activeFilterCount with correct pluralization, plus search-only and filters-plus-search states
  • Hidden while idle unless showWhenIdle (then reads "all records visible" with no clear action)
  • Tinted with the primary accent whenever the view is narrowed; role="status" announces changes to assistive tech
  • Every visible string overridable for i18n (recordsLabel, filterLabel/filtersLabel, clearLabel, …)
  • Framework-agnostic: filter state lives in the host — pairs with AG Grid, DataVis, or any list

Screenshots

Light Dark
FilterSummaryBar light FilterSummaryBar dark

Provenance

Port of waggleline/app/imports/ui/components/filters/FilterSummaryBar.tsx (used across its AG Grid pages); teal hardcodes → primary tokens, FontAwesome → lucide Filter/X, ml-auto → logical ms-auto.

Testing

  • 7 unit tests (idle hide/show, count formatting + pluralization, search states, clear action, i18n overrides)
  • 5 stories incl. an interactive add-a-filter demo
  • typecheck / lint / format / rtl:scan clean; combined batch suite 651/651

Ported from waggleline's grid pages: 'X of Y records — N filters
active · Clear all', hidden while idle unless showWhenIdle, tinted
with the primary accent when narrowing. Teal hardcodes become primary
tokens, FontAwesome becomes lucide, and every visible string is
overridable for i18n.
Copilot AI lite review requested due to automatic review settings August 23, 2026 04:04

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new FilterSummaryBar component to the design system to display an always-on “filtered results” summary for grids/lists (filtered/total counts, active filter count, and search state), with an optional idle display mode.

Changes:

  • Introduces FilterSummaryBar React component with styling, accessibility semantics (role="status"), and configurable labels.
  • Adds unit tests and Storybook stories (including an interactive demo) for the new component.
  • Exposes the component via package exports (src/index.ts) and build entrypoints (tsup.config.ts).

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
tsup.config.ts Adds build entrypoint for FilterSummaryBar.
src/index.ts Re-exports FilterSummaryBar from the public package API.
src/components/FilterSummaryBar/index.ts Barrel export for component + props.
src/components/FilterSummaryBar/FilterSummaryBar.tsx New summary bar component implementation and public props.
src/components/FilterSummaryBar/FilterSummaryBar.test.tsx Unit tests covering idle/active states, pluralization, clear action, and label overrides.
src/components/FilterSummaryBar/FilterSummaryBar.stories.tsx Storybook stories including interactive “add a filter” example.
Suppressed comments (1)

src/components/FilterSummaryBar/FilterSummaryBar.tsx:125

  • The combined state renders a hardcoded "+ search" suffix, which is user-visible and not overridable for i18n (and it also differs from the searchActiveLabel text used in the search-only state).
        {hasSearchText && activeFilterCount === 0 && (
          <> &mdash; {searchActiveLabel}</>
        )}
        {hasSearchText && activeFilterCount > 0 && <> + search</>}
        {!isFiltering && showWhenIdle && <> &mdash; {allVisibleLabel}</>}

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/components/FilterSummaryBar/FilterSummaryBar.tsx Outdated
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Aug 23, 2026

Copy link
Copy Markdown

Deploying ui with  Cloudflare Pages  Cloudflare Pages

Latest commit: 66cd9e4
Status: ✅  Deploy successful!
Preview URL: https://d2dc74ba.ui-6d0.pages.dev
Branch Preview URL: https://feat-filter-summary-bar.ui-6d0.pages.dev

View logs

Copilot AI review requested due to automatic review settings August 23, 2026 04:32

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated no new comments.

Suppressed comments (3)

Previously missed (3) — in code that hasn't changed since the last review.

src/components/FilterSummaryBar/FilterSummaryBar.tsx:84

  • The live region is missing explicit aria-live configuration. Elsewhere in the codebase, status regions typically specify aria-live (and often aria-atomic) to ensure consistent announcements (e.g. DropzoneOverlay.tsx:97-99, ConnectionStatus.tsx:386-389). Adding these here makes the announcement behavior more predictable across screen readers.
    <div
      ref={ref}
      role="status"
      className={cn(

src/components/FilterSummaryBar/FilterSummaryBar.tsx:148

  • Add a displayName for the forwarded-ref component. Many components in this repo set it for better DevTools output (e.g. Avatar.tsx:122, Alert.tsx:106).
});

src/components/FilterSummaryBar/FilterSummaryBar.tsx:140

  • The "Clear all" button doesn’t include the project’s standard focus-visible ring styles, which can make keyboard focus hard to see. Other inline icon buttons include these classes (e.g. Alert.tsx:91-95, CountBadge.tsx:43-44).
          className={cn(
            'ms-auto flex items-center gap-1.5 rounded-md px-2 py-1 text-xs font-medium transition-colors',
            'text-primary-700 hover:bg-primary-500/15 dark:text-primary-300'
          )}

@garrity-miepub
garrity-miepub self-requested a review September 2, 2026 17:57
Copilot AI review requested due to automatic review settings September 3, 2026 23:46

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 6 comments.

Comment thread src/components/FilterSummaryBar/FilterSummaryBar.tsx Outdated
Comment thread src/components/FilterSummaryBar/FilterSummaryBar.tsx Outdated
Comment thread src/components/FilterSummaryBar/FilterSummaryBar.test.tsx
Comment thread src/components/FilterSummaryBar/FilterSummaryBar.tsx Outdated
Comment thread src/tailwind-preset.cjs
Comment thread src/tailwind-preset.ts
… record label, localized filter count, safelist dedupe
Copilot AI review requested due to automatic review settings September 3, 2026 23:54

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.

Suppressed comments (2)

Previously missed (1) — in code that hasn't changed since the last review.

src/components/FilterSummaryBar/FilterSummaryBar.tsx:94

  • {...props} is spread after role="status", so a consumer-provided role prop can override the status role and break the intended assistive-tech announcement behavior. If the role should always be status, spread props first (or strip role from incoming props) so it can’t be overridden.

src/components/FilterSummaryBar/FilterSummaryBar.test.tsx:67

  • This assertion assumes an en-US thousands separator ("8,911"), but toLocaleString() output depends on the runtime’s default locale and the test setup doesn’t configure one. Using a regex here avoids locale-dependent failures while still verifying the content.
    expect(screen.getByRole('status')).toHaveTextContent('1 of 8,911 record —');

Comment thread src/components/FilterSummaryBar/FilterSummaryBar.test.tsx Outdated
Copilot AI review requested due to automatic review settings September 4, 2026 00:01

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated no new comments.

Suppressed comments (4)

Previously missed (3) — in code that hasn't changed since the last review.

src/components/FilterSummaryBar/FilterSummaryBar.tsx:94

  • {...props} is spread after role="status", so a consumer-provided role will override the live-region behavior (and potentially break the accessibility guarantee implied by the component). Move the spread before role to keep the status role enforced.
    src/components/FilterSummaryBar/FilterSummaryBar.tsx:133
  • PR description says the idle state (when showWhenIdle is true and no filters/search are active) “reads "all records visible"”, but the current render still includes counts/record labels and appends “— all records visible”. If the intended UX is label-only while idle, the render logic should switch to only allVisibleLabel (and tests/stories updated accordingly).
    src/components/FilterSummaryBar/FilterSummaryBar.tsx:10
  • The prop doc says consumers can pass 0 when totalCount is unknown, but 0 can also be a valid known total (empty dataset). Suggest documenting undefined as the “unknown” signal and letting 0 mean an actual total of zero.

This issue also appears on line 110 of the same file.

src/components/FilterSummaryBar/FilterSummaryBar.tsx:110

  • totalCount is rendered only when it’s truthy ({totalCount ? ...}), which means a valid totalCount={0} (empty dataset) will incorrectly omit the “of 0” portion. Consider checking for a finite number so 0 still renders and undefined/NaN do not.
        {totalCount ? (

…utage timeouts

The visual-test webServer (npx http-server) and the a11y job (pnpm dlx
http-server / wait-on) downloaded packages from the npm registry at run
time. During registry outages the download hangs, the server never
starts, and Playwright's 120s webServer timeout fails the job (run
33820036956). Pin both as devDependencies and use pnpm exec so test
startup requires no network.
Copilot AI review requested due to automatic review settings September 4, 2026 00:11

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 12 changed files in this pull request and generated 2 comments.

Files not reviewed (1)
  • pnpm-lock.yaml: Generated file

Comment thread src/components/FilterSummaryBar/FilterSummaryBar.tsx
Comment thread src/components/FilterSummaryBar/FilterSummaryBar.tsx Outdated
…e idle state

Move role="status" from the container div to the text span so the
clear button no longer lives inside the live region (avoids repeated
button announcements on count changes). When idle with showWhenIdle,
render only allVisibleLabel instead of counts + label, matching the
documented contract. Addresses Copilot review comments r3929798497
and r3929798523.
Copilot AI review requested due to automatic review settings September 4, 2026 00:25

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 12 changed files in this pull request and generated no new comments.

Files not reviewed (1)
  • pnpm-lock.yaml: Generated file

…live-region attrs, displayName

Addresses the suppressed Copilot review findings:
- totalCount rendered via a finite-number check so a real total of 0
  shows 'of 0' (doc now says omit = unknown); test added
- clear button gets the standard focus-visible ring classes (safelisted
  focus-visible:ring-offset-2 in both preset twins)
- explicit aria-live=polite / aria-atomic=true on the status span,
  matching DropzoneOverlay/ConnectionStatus conventions
- displayName set per repo convention
Copilot AI review requested due to automatic review settings September 4, 2026 00:44

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 12 changed files in this pull request and generated no new comments.

Files not reviewed (1)
  • pnpm-lock.yaml: Generated file

@garrity-miepub
garrity-miepub merged commit 014483b into main Sep 4, 2026
11 checks passed
@garrity-miepub
garrity-miepub deleted the feat/filter-summary-bar branch September 4, 2026 01:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants